As computer science has evolved, object oriented programming has become one of many familiar models employed by designers and programmers to implement functionality within computer systems. The object model can comprise of one or more objects that act on each other, as opposed to a traditional model that comprises of programs that are a collection of functions, or simply a list of instructions. Each object is capable of receiving messages, processing data, sending messages to other objects and can be viewed as an independent machine with a distinct role or responsibility.
The object lifetime (or life cycle) of an object, in object-oriented programming, is the time between an object's creation (also known as instantiation or construction) and an object's destruction. An object can be created and/or destroyed automatically (such as a managed object) or manually (such as a native or unmanaged object). Managed objects may be described in terms of a data type (e.g., metadata) and automatically collected (e.g., reclaimed) by a managed environment such as a garbage collector that removes the object from memory when the object is no longer being accessed. In contrast, unmanaged objects can be allocated from a standard operating system heap, wherein the object itself is responsible for freeing memory it employs when references to the object no longer exist. This can be accomplished through well-known techniques such as reference counting, for example.
As described above, managed objects can be allocated from a managed heap and automatically garbage collected. In order to achieve this, references to managed objects can be traced. When a last reference to an object is removed, the garbage collector can reclaim the memory occupied by the object, mitigating the need to reference count managed objects. Tracing is possible within managed code because the managed environment can keep track of outstanding references that exist on an object. As each new object reference is declared within managed code, the managed environment can add the reference to a list of live references. At any given time, the managed environment, rather than the object itself, can thus be aware of live references that exist on a given object. As references fall out of scope or change value, the list of live references can be updated, and as long as a reference remains within managed code, the managed environment can trace it.
The implementation of an object can be split across a native part and a managed part (peers). The native peer's lifetime can be controlled with a reference counting technique whereas the garbage collector, as discussed above, can manage the managed peer's lifetime. When some of the references between managed objects go through native code, the managed objects can be leaked or pre-maturely collected.
In multiple managed/native object pair scenarios, as long as a reference to either of the objects exists, the pair must live. Traditional solutions require multiple garbage collections to reclaim the objects and are prone to memory leaks, wherein the objects do not get collected even though there are no external references to the objects, and premature collection, wherein the garbage collector reclaims the objects even though an unmanaged reference may exist.